package com.group.common.utils;

import com.group.common.users.Sex;
import com.group.common.users.NEPSUser;
import com.group.nepm.statisticDataManagement.entity.StatisticData;
import com.group.neps.entity.*;
import com.group.nepg.entity.AccurateAqiData;
import com.group.nepg.entity.AccurateAqiDataFactory;

import java.io.*;
import java.time.LocalDate;
import java.util.*;

/**
 * 生成测试数据
 *
 * @author 刘海翔
 * @version 1.0
 */
public class DataGenerator {

    private static final Random RANDOM = new Random();
    private static HashMap<String, Province> locationMap;
    static {
        try {
            loadLocationMap("group/data/location_hashmap.dat");
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException("加载地理位置数据失败", e);
        }
    }

    /**
     * 从指定路径加载序列化的 locationMap
     *
     * @param filePath 文件路径
     */
    private static void loadLocationMap(String filePath) throws IOException, ClassNotFoundException {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath))) {
            locationMap = (HashMap<String, Province>) ois.readObject();
        }
    }

    /**
     * 获取所有省份列表
     *
     * @return 所有省份列表
     */
    private static ArrayList<Province> getAllProvinces() {
        return new ArrayList<>(locationMap.values());
    }

    /**
     * 随机选择一个省份
     *
     * @return 随机选取的省份
     */
    private static Province getRandomProvince() {
        ArrayList<Province> provinces = getAllProvinces();
        return provinces.get(RANDOM.nextInt(provinces.size()));
    }

    /**
     * 从指定省份中随机选择一个城市
     *
     * @param province 省份
     * @return 随机选取的城市
     */
    private static City getRandomCityInProvince(Province province) {
        ArrayList<City> cities = new ArrayList<>(province.getCities().values());
        if (cities.isEmpty()) {
            throw new IllegalStateException("省份 " + province.getName() + " 没有对应城市");
        }
        return cities.get(RANDOM.nextInt(cities.size()));
    }

    /**
     * 生成一个合法的 Location（城市一定在选中的省内）
     *
     * @return 生成的 Location
     */
    public static Location generateRandomLocation() {
        Province province = getRandomProvince();
        City city = getRandomCityInProvince(province);

        String address = "Address-" + UUID.randomUUID().toString();
        return new Location(province, city, address);
    }

    /**
     * 生成指定数量的 RowAqiData 列表
     *
     * @param count 生成数量
     * @return 生成的 RowAqiData 列表
     */
    public static ArrayList<RowAqiData> generateRandomRowAqiDataList(int count) {
        ArrayList<RowAqiData> dataList = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            Location location = generateRandomLocation();
            RowAqiLevel rowAqiLevel = getRandomRowAqiLevel();

            String username = "user" + i;
            String password = "pass" + i;
            String phoneNumber = "1380000" + String.format("%04d", i);
            String remark = "Remark of user " + i;
            Sex sex = getRandomSex();

            NEPSUser user = new NEPSUser(username, password, phoneNumber, remark, sex);
            LocalDate date = LocalDate.now().minusDays(RANDOM.nextInt(365));
            String aqiRemark = "Sample Remark " + i;

            RowAqiData rowAqiData = new RowAqiData(user, date, location, rowAqiLevel, aqiRemark);
            dataList.add(rowAqiData);
        }
        return dataList;
    }

    /**
     * 生成指定数量的 AccurateAqiData 列表
     *
     * @param count 生成数量
     * @return 生成的 AccurateAqiData 列表
     */
    public static ArrayList<AccurateAqiData> generateRandomAccurateAqiDataList(int count) {
        ArrayList<AccurateAqiData> dataList = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            double co = RANDOM.nextDouble() * 100;
            double pm = RANDOM.nextDouble() * 300;
            double so2 = RANDOM.nextDouble() * 2000;
            AccurateAqiData data = AccurateAqiDataFactory.getAccurateAqiData(co, pm, so2);
            dataList.add(data);
        }
        return dataList;
    }

    /**
     * 生成指定数量的 StatisticData 列表
     *
     * @param count 生成数量
     * @return 生成的 StatisticData 列表
     */
    public static ArrayList<StatisticData> generateRandomStatisticDataList(int count) {
        ArrayList<StatisticData> dataList = new ArrayList<>();

        List<RowAqiData> rowDataList = generateRandomRowAqiDataList(count);
        List<AccurateAqiData> accurateDataList = generateRandomAccurateAqiDataList(count);

        for (int i = 0; i < count; i++) {
            StatisticData statisticData = createStatisticData(rowDataList.get(i), accurateDataList.get(i));
            dataList.add(statisticData);
        }

        return dataList;
    }

    /**
     * 根据 RowAqiData 和 AccurateAqiData 创建 StatisticData
     *
     * @param rowAqiData RowAqiData
     * @param  accurateAqiData AccurateAqiData
     * @return 创建的 StatisticData
     */
    public static StatisticData createStatisticData(RowAqiData rowAqiData, AccurateAqiData accurateAqiData) {
        StatisticData statisticData = new StatisticData();
        statisticData.setRowAqiData(rowAqiData);
        statisticData.setAccurateAqiData(accurateAqiData);
        return statisticData;
    }

    /**
     * 获取随机 RowAqiLevel
     *
     * @return 随机的 RowAqiLevel
     */
    private static RowAqiLevel getRandomRowAqiLevel() {
        RowAqiLevel[] levels = RowAqiLevel.values();
        return levels[RANDOM.nextInt(levels.length)];
    }

    /**
     * 获取随机性别
     *
     * @return 随机的性别
     */
    private static Sex getRandomSex() {
        Sex[] sexes = Sex.values();
        return sexes[RANDOM.nextInt(sexes.length)];
    }
}
